<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Common\RedisCache\FetchVideoCache;
use App\Common\RedisCache\FetchVideoListCache;
use App\Common\RedisCache\UserCache;
use App\Models\Article;
use co;
use Co\WaitGroup;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use function Co\run;
use function Symfony\Component\String\b;

/**
 * 拉取视频M3U8路径，入队
 * @class FetchVideoM3U8URL
 */
class FetchVideoM3U8URL extends Command
{
    protected $signature   = 'FetchVideoM3U8URL {type?}';
    protected $description = '拉取视频M3U8路径后入队';

    public function handle()
    {
        $argument = $this->argument('type');
        //5分钟一次
        if ($argument == 'publish') {
            return $this->publishList();
        }
        //1分钟一次
        if ($argument == 'consumer') {
            return $this->consumerList();
        }
    }

    /**
     * @return bool
     */
    public function publishList(): bool
    {
        $userCache = new UserCache();
        $userCache->setKeyParameter(['fetchVideo']);
        $page = $userCache->get();
        $file = fopen('sh/hots.txt','r');
        $url = fgets($file);
        fclose($file);
        $url  = 'https://'.$url;
        $localUrl  = 'storage/video/'.$page.'.html';
        if (!file_exists($localUrl)) {
            Log::info($localUrl.'--file not exists!');
            return false;
        }
        $html = file_get_contents($localUrl);
        $preg = '#<div id="listpage_video_set"><ul>(.*)</ul></div>#isU';
        preg_match_all($preg, $html, $result);
        $html1 = $result[1][0] ?? '';
        if ($html1 == '') {
            $userCache->set($page+1);
            return true;
        }
        $preg  = '#<a href="(.*)".*title="(.*)">.*</a>#isU';
        preg_match_all($preg, $html1, $matchRes);
        $urlInfo   = $matchRes[1];
        $titleInfo = $matchRes[2];
        $redis     = new FetchVideoCache();
        $redis->setKeyParameter();
        $listResult = [];
        $setArray  = [];
        run(function () use (&$listResult, $urlInfo, $redis, $url, $titleInfo, &$setArray) {
            $waitGroup = new WaitGroup();
            $waitGroup->add(count($urlInfo));
            foreach ($urlInfo as $k=>$v) {
                go(function () use ($waitGroup, &$listResult, $v, $redis, $url, $titleInfo, $k, &$setArray) {
                    $substr = substr($v,strpos($v,'=')+1);
                    if (strpos($v,'video_id') && !$redis->memberExists($substr)) {
                        $v = $url . str_replace('video_info.html','video_play.html', $v);
                        @$html = file_get_contents($v);
                        if (is_bool($html)) {
                            $waitGroup->done();
                            return false;
                        }
                        $preg = '#var vPlayerM3u8Url = "(.*)";#isU';
                        preg_match_all($preg, $html, $m3u8Res);
                        $m3u8Res = $m3u8Res[1][0] ?? 0;
                        if ($m3u8Res) {
                            $setArray[] = $substr;
                            $listResult[] = [
                                'm3u8url' => $m3u8Res,
                                'title'   => $titleInfo[$k],
                                'text'    => $v,
                            ];
                        }
                    }
                    $waitGroup->done();
                });
            }
            $waitGroup->wait();
        });

        if (count($listResult) >= count($urlInfo) - 4) {
            $listCache = new FetchVideoListCache();
            $listCache->setKeyParameter();
            foreach ($listResult as $m3u8Res) {
                $listCache->lPush([
                    'm3u8url' => $m3u8Res['m3u8url'],
                    'title'   => $m3u8Res['title'],
                    'text'    => $m3u8Res['text'],//详情地址
                ]);
            }
            $userCache->set($page+1);
            $redis->set($setArray);
            Log::info('---done ----');
            return true;
        }
        if (empty($listResult)) {
            $userCache->set($page+1);
        }
        Log::info('---not done ----', ['$listResult'=>$listResult,'$urlInfo'=>$urlInfo]);
        return true;
    }

    public function consumerList(): bool
    {
        if ($this->continueExecFfmpeg()) {
            $listCache = new FetchVideoListCache();
            $listCache->setKeyParameter();
            $popResult = $listCache->rPop();
            if (!$popResult) {
                Log::info('从队列拿到的数据：'.$popResult);
                return false;
            }
            $exists = Article::query()->where('title', $popResult['title'])->exists();
            if ($exists) {
                Log::info('重复记录--', $popResult);
                return true;
            }
            $id = Article::query()->insertGetId($popResult);
            Log::info('fetching...', $popResult);
            $dir = '/tmp/video'.date('Ymd').'bySyncList/';
            @mkdir($dir);
            $exec = '/opt/homebrew/Cellar/ffmpeg/5.1.2/bin/ffmpeg -i '.$popResult['m3u8url'].' -fs 419430400 -to 7200 "'.$dir.$popResult['title'].'".mp4';
            Log::info($exec);
            system($exec);
            Article::query()->whereId($id)->update(['status'=>1]);
            Log::info('fetched:', $popResult);
        }
        return true;
    }

    /**
     * @return bool
     */
    public function continueExecFfmpeg() : bool
    {
        $wcShell = 'ps aux | grep ffmpeg | '."awk '{if($8 == ".'"R"'.") print($8)}'".' | wc -l';
        $wcR = (int)exec($wcShell);
        $wcShell2 = 'ps aux | grep ffmpeg | '."awk '{if($8 == ".'"R+"'.") print($8)}'".' | wc -l';
        $wc2 = (int)exec($wcShell2);
        $wcShell3 = 'ps aux | grep ffmpeg | '."awk '{if($8 == ".'"S"'.") print($8)}'".' | wc -l';
        $wc3 = (int)exec($wcShell3);
        $wc = $wcR+$wc2;
        if ($wc > 10) {
            Log::info('还没执行完的ffmpeg进程数：R：'.$wcR);
            Log::info('还没执行完的ffmpeg进程数：R+：'.$wc2);
            Log::info('还没执行完的ffmpeg进程数：S：'.$wc3);
            return false;
        }
        if ($wc3 > 20) {
            Log::info('还没执行完的ffmpeg进程数：S：'.$wc3);
            $ids = Article::query()->where('status', 0)->pluck('id');
            system('killall -9 ffmpeg');
            usleep(10000);
            Article::query()->whereIn('id',$ids)->update(['status'=>0]);
        }
        return true;
    }
}